`timescale 1ns/ 1ns

module spi_master_tm(
	input  rst,
	input  clk,
	output spi_ssel,
	output spi_sck,
	output spi_mosi,
	input  spi_miso
	);
	
	wire       di_req;
	reg [7:0]  di=0;
	reg        wren=0;
	wire       wr_ack;
	wire       do_valid;
	wire [7:0] data;
	
	spi_master #(.N(8)) u_spi_master(
	.sclk_i     (clk       ),
	.pclk_i     (clk       ),
	.rst_i      (rst       ),
	.spi_ssel_o (spi_ssel  ),
	.spi_sck_o  (spi_sck   ),
	.spi_mosi_o (spi_mosi  ),
	.spi_miso_i (spi_miso  ),
	.di_req_o   (di_req    ),
	.di_i       (di        ),
	.wren_i     (wren      ),
	.wr_ack_o   (wr_ack    ),
	.do_valid_o (do_valid  ),
	.do_o       (data      )
	);
	
task send_byte;
	input is_first;
	input [7:0] data;
begin
	if (is_first==1'b0) begin
		@(posedge clk);
		while (di_req==1'b0) @(posedge clk);
	end

	@(posedge clk);
	wren=1'b1;
	di=data;
	@(posedge clk);
	while (wr_ack==1'b0) @(posedge clk);
	@(posedge clk);
	wren=1'b0;
	@(posedge clk);
	while (wr_ack==1'b1) @(posedge clk);
end
endtask

task send_finish;
begin
	@(posedge clk);
	while(spi_ssel==1'b0) @(posedge clk);
end
endtask

task rec_byte;
	output [7:0] rdata;
begin
	@(posedge clk);
	while (do_valid==1'b0) @(posedge clk);
	rdata=data; 
	@(posedge clk);
	while (do_valid==1'b1) @(posedge clk);
end
endtask

task spi_op;
	input [7:0] cmd;
	input [31:0] addr;
	input [7:0] bytemsk; 
	input [31:0] wdata;
	
	reg [31:0] rdata;
begin
	send_byte(1,cmd);
	send_byte(0,addr[31:24]);
	send_byte(0,addr[23:16]);
	send_byte(0,addr[15:8]);
	send_byte(0,addr[7:0]);
	send_byte(0,bytemsk);
	fork
		begin
			send_byte(0,wdata[31:24]);
			send_byte(0,wdata[23:16]);
			send_byte(0,wdata[15:8]);
			send_byte(0,wdata[7:0]);
			send_finish;
			if(cmd==8'h0) $display("spi wr : addr = %h , wdata = %h",addr,wdata);
		end
		begin
			rec_byte(rdata[31:24]);//drop
			rec_byte(rdata[31:24]);
			rec_byte(rdata[23:16]);
			rec_byte(rdata[15:8]);
			rec_byte(rdata[7:0]);
			if(cmd==8'h1) $display("spi rd : addr = %h , rdata = %h" ,addr ,rdata);
		end
	join
end
endtask;
			
endmodule		
		